package org.xserver.component.core.dispatch;

import org.xserver.component.core.XServerHttpContextAttachment;
import org.xserver.component.handler.ext.WriteHandler;
import org.xserver.component.handler.ext.WriteHandlerFactory.ResponseType;

/**
 * The abstract request dispatch define process event flow as follow:
 * <ul>
 * <li>1. {@link #doRequest(XServerHttpContextAttachment)} represent server
 * accept the request and process into business logic.</li>
 * <li>2. {@link #wrapResponse(XServerHttpContextAttachment, Object)} after
 * business result, wrap the result. For example: change the data structure, set
 * some prototype's headers</li>
 * <li>3. {@link #writeResponse(XServerHttpContextAttachment, Object)} will
 * write response to client.</li>
 * </ul>
 * 
 * @author wangj
 * @since 2016/07/15
 *
 */
public abstract class AbstractRequestDispatch implements RequestDispatch {

	/**
	 * Default process event flow: business -&gt wrap -&gt write to client
	 */
	@Override
	public void requestDispatch(XServerHttpContextAttachment attachment,WriteHandler writeHandler)
			throws Exception {
		doRequest(attachment,writeHandler);
		//return wrapResponse(attachment, result);
	}

	/**
	 * Do request for remote client, the subclass implements
	 * {@link #doRequest(XServerHttpContextAttachment)} means it support someone
	 * request type, for example, the interface request just response business
	 * result, the file request should response specified file.
	 * @param writeHandler 
	 */
	protected abstract void doRequest(XServerHttpContextAttachment attachment, WriteHandler writeHandler)
			throws Exception;

	/**
	 * Wrap response, after {@link #doRequest(XServerHttpContextAttachment)} the
	 * result maybe configure something, for example set head. The subclass can
	 * wrap either context or result. If nothing to wrap, subclass needn't to
	 * extend this method
	 * 
	 * @param attachment
	 * @throws Exception
	 */
	protected Object wrapResponse(XServerHttpContextAttachment attachment,
			Object result) throws Exception {
		return result;
	}

	/**
	 * get the response to client type
	 * 
	 * @param attachment
	 * @return
	 */
	public abstract ResponseType getResponsePrototype(
			XServerHttpContextAttachment attachment);

	public abstract boolean accept(XServerHttpContextAttachment attachment);

	/**
	 * Write response to client
	 * 
	 * @param attachment
	 * @param result
	 * @throws Exception
	 */
//	protected void writeResponse(XServerHttpContextAttachment attachment,
//			Object result) throws Exception {
//		WriteHandler writeHandler = (WriteHandler) attachment.getAttachment()
//				.get(WriteHandler.class.getSimpleName());
//		writeHandler.writeResponse(attachment, result);
//	}

	/**
	 * The request dispatch unified name is class simple name
	 */
	@Override
	public String getName() {
		return this.getClass().getSimpleName();
	}

}
